<?php
/**
 * @file
 */

/**
 * Implements of hook_entity_info()
 */
function customer_entity_info() {
  $return = array(
    'customer' => array(
      'label' => t('customer'),
      'controller class' => 'FFScustomerController',
      'base table' => 'customer',
      'uri callback' => 'customer_uri',
      'fieldable' => TRUE,
      'entity keys' => array(
        'id' => 'aid',
      ),
      'bundles' => array(
        'customer' => array(
          'label' => t('customer'),
          'admin' => array(
            'path' => 'admin/config/customer',
            'access arguments' => array('administer customer'),
          ),
        ),
      ),
      'view modes' => array(
        'full' => array(
          'label' => t('customer'),
          'custom settings' => FALSE,
        ),
      ),
    ),
  );
  return $return;
}

/**
 * Implements callback_entity_info_uri().
 */
function customer_uri($customer) {
  return array(
    'path' => 'customer/view/' . $customer->aid,
    'options' => array('fragment' => 'customer-' . $customer->aid),
  );
}

/**
 * Implements hook_field_info_alter().
 */
function customer_client_field_info_alter(&$info) {
  // Add the 'customer_form' instance setting to all field types.
  foreach ($info as $field_type => &$field_type_info) {
    $field_type_info += array('instance_settings' => array());
    $field_type_info['instance_settings'] += array(
      'customer_edit' => FALSE,
    );
  }
}

/**
 * Implements hook_field_extra_fields().
 */
function customer_field_extra_fields() {
  $return['customer']['customer'] = array(
    'form' => array(
      'name' => array(
        'label' => t('customer Name'),
        'description' => t('Form elements.'),
        'weight' => 0,
      ),
      'tel' => array(
        'label' => t('Telephone'),
        'description' => t('Form elements.'),
        'weight' => 1,
      ),
      'fax' => array(
        'label' => t('Fax'),
        'description' => t('Form elements.'),
        'weight' => 2,
      ),
      'hangding_fee' => array(
        'label' => t('Hangding Fee'),
        'description' => t('Form elements.'),
        'weight' => 3,
      ),
      'status' => array(
        'label' => t('Status'),
        'description' => t('Form elements.'),
        'weight' => 4,
      ),
      'remark' => array(
        'label' => t('Remark'),
        'description' => t('Form elements.'),
        'weight' => 5,
      )

    ),
    'display' => array(
      'summary' => array(
        'label' => t('customer'),
        'description' => t('customer module client view element.'),
        'weight' => 5,
      ),
    ),
  );

  return $return;
}

/**
 * Load the entire word by wid.
 *
 * @param $wid
 *   The identifying comment id.
 * @param $reset
 *   Whether to reset the internal static entity cache. Note that the static
 *   cache is disabled in comment_entity_info() by default.
 *
 * @return
 *   The comment object.
 */
function customer_load($aid, $reset = FALSE) {
  $customer = customer_load_multiple(array($aid), array(), $reset);
  return $customer ? $customer[$aid] : FALSE;
}

/**
 * Load entities from the database.
 *
 * @param $aids
 *   An array of word IDs.
 * @param $conditions
 *   (deprecated) An associative array of conditions on the {wordgames}
 *   table, where the keys are the database fields and the values are the
 *   values those fields must have. Instead, it is preferable to use
 *   EntityFieldQuery to retrieve a list of entity IDs loadable by
 *   this function.
 * @param $reset
 *   Whether to reset the internal static entity cache. Note that the static
 *   cache is disabled in wordgame_entity_info() by default.
 *
 * @return
 *   An array of comment objects, indexed by word ID.
 *
 * @see entity_load()
 * @see EntityFieldQuery
 *
 * @todo Remove $conditions in Drupal 8.
 */
function customer_load_multiple($aids = array(), $conditions = array(), $reset = FALSE) {
  return entity_load('customer', $aids, $conditions, $reset);
}

/**
 * Save word
 */
function customer_save($customer) {
  $transaction = db_transaction();
  try {
    // Load the stored entity, if any.
    if (!empty($customer->aid) && !isset($customer->original)) {
      $customer->original = entity_load_unchanged('customer', $customer->aid);
    }

    global $user;

    field_attach_presave('customer', $customer);

    // Determine if we will be inserting a new node.
    if (!isset($customer->is_new)) {
      $customer->is_new = empty($customer->aid);
    }

    if (empty($customer->modified)){
      $customer->modified = REQUEST_TIME;
    }

    // The changed timestamp is always updated for bookkeeping purposes,
    // for example: revisions, searching, etc.
    $customer->changed = REQUEST_TIME;

    $customer->timestamp = REQUEST_TIME;
    $update_customer = TRUE;

    // Let modules modify the node before it is saved to the database.
    module_invoke_all('customer_presave', $customer);
    module_invoke_all('entity_presave', $customer, 'customer');

    // When saving a new node revision, unset any existing $node->vid so as to
    // ensure that a new revision will actually be created, then store the old
    // revision ID in a separate property for use by node hook implementations.
    if (!$customer->is_new && !empty($customer->revision) && $customer->vid) {
      $customer->old_vid = $customer->vid;
      unset($customer->vid);
    }

    // Save the entity and entity revision.
    if ($customer->is_new) {
      // For new customer, save new records for the customer itself
      drupal_write_record('customer', $customer);
      _customer_save_revision($customer, $user->uid);
      $op = 'insert';
    }
    else {
      // For existing customer, update the customer record which matches the value of
      // $customer->aid.
      drupal_write_record('customer', $customer, 'aid');
      if (!empty($customer->revision)) {
        _customer_save_revision($customer, $user->uid);
      }
      else {
        _customer_save_revision($customer, $user->uid, 'vid');
        $update_customer = FALSE;
      }
      $op = 'update';
    }

    if ($update_customer) {
      db_update('customer')
        ->fields(array('vid' => $customer->vid))
        ->condition('aid', $customer->aid)
        ->execute();
    }

    // Save fields.
    $function = "field_attach_$op";
    $function('customer', $customer);

    module_invoke_all('customer_' . $op, $customer);
    module_invoke_all('entity_' . $op, $customer, 'customer');

    // Clear internal properties.
    unset($customer->is_new);
    unset($customer->original);
    // Clear the static loading cache.
    entity_get_controller('customer')->resetCache(array($customer->aid));

    // Ignore slave server temporarily to give time for the
    // saved customer to be propagated to the slave.
    db_ignore_slave();
  }
  catch (Exception $e) {
    $transaction->rollback();
    watchdog_exception('customer', $e);
    throw $e;
  }
}

/**
 * Helper function to save a revision with the uid of the current user.
 *
 * The resulting revision ID is available afterward in $node->vid.
 *
 * @param $node
 *   A node object.
 * @param $uid
 *   The current user's UID.
 * @param $update
 *   (optional) An array of primary keys' field names to update.
 */
function _customer_save_revision($customer, $uid, $update = NULL) {
  $temp_uid = $customer->uid;
  $customer->uid = $uid;
  if (isset($update)) {
    drupal_write_record('customer_revision', $customer, $update);
  }
  else {
    drupal_write_record('customer_revision', $customer);
  }
  // Have node object still show node owner's uid, not revision author's.
  $customer->uid = $temp_uid;
}

/**
 * Deletes a wordgame word.
 *
 * @param $aid
 *   A customer ID.
 */
function customer_delete($aid) {
  customer_delete_multiple(array($aid));
}

/**
 * Deletes multiple words.
 *
 * @param $aids
 *   An array of word IDs.
 */
function customer_delete_multiple($aids) {
  $transaction = db_transaction();
  if (!empty($aids)) {
    $agencies = customer_load_multiple($aids, array());

    try {
      foreach ($agencies as $aid => $customer) {
        // Call the node-specific callback (if any):
        module_invoke_all('customer_delete', $customer);
        module_invoke_all('entity_delete', $customer, 'customer');
        field_attach_delete('customer', $customer);
      }
      // Delete after calling hooks so that they can query customer tables as needed.
      db_delete('customer')
        ->condition('aid', $aids, 'IN')
        ->execute();
      db_delete('customer_revision')
        ->condition('aid', $aids, 'IN')
        ->execute();
    }
    catch (Exception $e) {
      $transaction->rollback();
      watchdog_exception('customer', $e);
      throw $e;
    }

    // Clear the page and block and node_load_multiple caches.
    entity_get_controller('customer')->resetCache();
  }
}

/**
 * Deletes a entity revision.
 *
 * @param $revision_id
 *   The revision ID to delete.
 */
function customer_revision_delete($revision_id) {
  if ($revision = customer_load(NULL, $revision_id)) {
    // Prevent deleting the current revision.
    $customer = customer_load($revision->aid);
    if ($revision_id == $customer->vid) {
      return FALSE;
    }

    db_delete('customer_revision')
      ->condition('aid', $revision->aid)
      ->condition('vid', $revision->vid)
      ->execute();
    module_invoke_all('customer_revision_delete', $revision);
    field_attach_delete_revision('customer', $revision);
    return TRUE;
  }
  return FALSE;
}

/**
 * Generates an array for rendering the given node.
 *
 * @param $node
 *   A node object.
 * @param $view_mode
 *   View mode, e.g. 'full', 'teaser'...
 * @param $langcode
 *   (optional) A language code to use for rendering. Defaults to the global
 *   content language of the current request.
 *
 * @return
 *   An array as expected by drupal_render().
 */
function customer_view($customer, $view_mode = 'full', $langcode = NULL) {
  if (!isset($langcode)) {
    $langcode = $GLOBALS['language_content']->language;
  }

  // Populate $node->content with a render() array.
  customer_build_content($customer, $view_mode, $langcode);

  $build = $customer->content;
  // We don't need duplicate rendering info in node->content.
  unset($customer->content);

  $build += array(
    '#theme' => 'customer',
    '#customer' => $customer,
    '#view_mode' => $view_mode,
    '#language' => $langcode,
  );



  // Add contextual links for this node, except when the node is already being
  // displayed on its own page. Modules may alter this behavior (for example,
  // to restrict contextual links to certain view modes) by implementing
  // hook_node_view_alter().
  if (!empty($customer->aid) && !($view_mode == 'full')) {
    $build['#contextual_links']['customer'] = array('customer', array($customer->aid));
  }

  // Allow modules to modify the structured node.
  $type = 'customer';
  drupal_alter(array('customer_view', 'entity_view'), $build, $type);

  return $build;
}

/**
 * Builds a structured array representing the node's content.
 *
 * The content built for the node (field values, comments, file attachments or
 * other node components) will vary depending on the $view_mode parameter.
 *
 * Drupal core defines the following view modes for nodes, with the following
 * default use cases:
 *   - full (default): node is being displayed on its own page (node/123)
 *   - teaser: node is being displayed on the default home page listing, on
 *     taxonomy listing pages, or on blog listing pages.
 *   - rss: node displayed in an RSS feed.
 *   If search.module is enabled:
 *   - search_index: node is being indexed for search.
 *   - search_result: node is being displayed as a search result.
 *   If book.module is enabled:
 *   - print: node is being displayed in print-friendly mode.
 * Contributed modules might define additional view modes, or use existing
 * view modes in additional contexts.
 *
 * @param $node
 *   A node object.
 * @param $view_mode
 *   View mode, e.g. 'full', 'teaser'...
 * @param $langcode
 *   (optional) A language code to use for rendering. Defaults to the global
 *   content language of the current request.
 */
function customer_build_content($customer, $view_mode = 'full', $langcode = NULL) {
  if (!isset($langcode)) {
    $langcode = $GLOBALS['language_content']->language;
  }

  // Remove previously built content, if exists.
  $customer->content = array();

  // Allow modules to change the view mode.
  $context = array(
    'entity_type' => 'customer',
    'entity' => $customer,
    'langcode' => $langcode,
  );
  drupal_alter('entity_view_mode', $view_mode, $context);

  // Build fields content.
  // In case of a multiple view, node_view_multiple() already ran the
  // 'prepare_view' step. An internal flag prevents the operation from running
  // twice.
  field_attach_prepare_view('customer', array($customer->aid => $customer), $view_mode, $langcode);
  entity_prepare_view('customer', array($customer->aid => $customer), $langcode);
  $customer->content += field_attach_view('customer', $customer, $view_mode, $langcode);

  // Always display a read more link on teasers because we have no way to know
  // when a teaser view is different than a full view.
  $links = array();
  $customer->content['links'] = array(
    '#theme' => 'links__customer',
    '#pre_render' => array('drupal_pre_render_links'),
    '#attributes' => array('class' => array('links', 'inline')),
  );

  // Allow modules to make their own additions to the node.
  module_invoke_all('customer_view', $customer, $view_mode, $langcode);
  module_invoke_all('entity_view', $customer, 'customer', $view_mode, $langcode);

  // Make sure the current view mode is stored if no module has already
  // populated the related key.
  $customer->content += array('#view_mode' => $view_mode);
}


/**
 * Constructs a drupal_render() style array from an array of loaded nodes.
 *
 * @param $nodes
 *   An array of nodes as returned by node_load_multiple().
 * @param $view_mode
 *   View mode, e.g. 'full', 'teaser'...
 * @param $weight
 *   An integer representing the weight of the first node in the list.
 * @param $langcode
 *   (optional) A language code to use for rendering. Defaults to NULL which is
 *   the global content language of the current request.
 *
 * @return
 *   An array in the format expected by drupal_render().
 */
function customer_view_multiple($agencies, $view_mode = 'teaser', $weight = 0, $langcode = NULL) {
  field_attach_prepare_view('customer', $agencies, $view_mode, $langcode);
  entity_prepare_view('customer', $agencies, $langcode);
  $build = array();
  foreach ($agencies as $customer) {
    $build[''][$customer->aid] = customer_view($customer, $view_mode, $langcode);
    $build[''][$customer->aid]['#weight'] = $weight;
    $weight++;
  }
  $build['']['#sorted'] = TRUE;
  return $build;
}

/**
 * Prepares a entity object for editing.
 *
 * Fills in a few default values, and then invokes hook_prepare() on the entity
 * type module, and hook_entity_prepare() on all modules.
 *
 * @param $entity
 *   A entity object.
 */
function customer_object_prepare($customer) {
  // If this is a new node, fill in the default values.
  if (!isset($customer->aid) || isset($customer->is_new)) {
    global $user;
    $customer->name = '';
    $customer->tel = '';
    $customer->fax = '';
    $customer->hangding_fee = '';
    $customer->status = 1;
    $customer->uid = $user->uid;
    $customer->remark = '';
    $customer->modified = REQUEST_TIME;
  }
  else {
    $customer->date = format_date($customer->modified, 'custom', 'Y-m-d H:i:s O');
    // Remove the log message from the original node object.
    $customer->log = NULL;
  }
  module_invoke_all('customer_prepare', $customer);
}

/**
 * Controller class for wordgame word.
 *
 * This extends the DrupalDefaultEntityController class, adding required
 * special handling for comment objects.
 */
class FFScustomerController extends DrupalDefaultEntityController {
  protected function attachLoad(&$agencies, $revision_id = FALSE) {
    // Call the default attachLoad() method. This will add fields and call
    // hook_wordgame_load().
    parent::attachLoad($agencies, $revision_id);
  }
}
